/*
@hehung
2023-2-8
转载请注明出处，版权由@hehung所有
email: 1398660197@qq.com
wechat: hehung95
*/

#include "hal_data.h"
#include "app_display.h"
#include "app_hs300x.h"
#include "app_isl29035.h"
#include "app_oled.h"
#include "app_rtc.h"
#include "oled_imgtab.h"
#include "app_buletooth.h"
#include "app_wifi.h"
#include "app_mq5.h"

#include <stdio.h>
#include <string.h>

#define DISP_DEBUG
#undef DISP_DEBUG

#ifdef DISP_DEBUG
#define LOG(fmt, ...) 	                printf(fmt, ##__VA_ARGS__)
#else
#define LOG(fmt, ...)
#endif


#define DISP_MAIN_CUT_TIME              (10U)   


typedef struct
{
    void (*disp_func)(void);    // display inteface function pointer
    uint16_t delay_time;        // refresh frequency
} s_DispType;


static void Disp_Startup(void);
static void Disp_MainMenu(void);
static void Disp_SensorMonitor(void);
static void Disp_LampCtrl(void);


static e_DispType disp_variant = DISP_INIT;
static e_DispType last_disp_variant = DISP_INIT;
static const s_DispType disp_list[] = 
{
    {.disp_func = Disp_Startup, .delay_time = 1000U},
    {.disp_func = Disp_MainMenu, .delay_time = 200U},
    {.disp_func = Disp_SensorMonitor, .delay_time = 100U},
    {.disp_func = Disp_LampCtrl, .delay_time = 100U}
};


// Display startup informations
static void Disp_Startup(void)
{
    /* initialize the OLED */
    OLED_Init();

    OLED_ShowString(12, 0, (const uint8_t*)"RA4M2-Gateway", 16, 1);
    OLED_ShowHzStringRow(32, 24, (const char*)"电子发烧友", 1);
    OLED_ShowString(64, 48, (const uint8_t*)"--hehung", 16, 1);
    OLED_Refresh_Gram();

    // waiting for 1s to enter the main menu
    disp_variant = DISP_MAIN_MENU;
}

// Display main 
static void Disp_MainMenu(void)
{
    char text[16];
    rtc_time_t curr_time;
    static uint8_t flag = 0;
    static uint8_t conn_flag = 0;
    const char *hz_week_char[] = {"日", "一", "二", "三", "四", "五", "六"};
    s_Hs300xDataType humi_temp;
    uint8_t x;
    
    // display time
    curr_time = Rtc_GetDateTime();
    sprintf(text, "%02d", curr_time.tm_hour);
    OLED_ShowString(16, 14, (const uint8_t*)text, 36, 1);
	sprintf(text, "%02d", curr_time.tm_min);
	OLED_ShowString(60, 14, (const uint8_t*)text, 36, 1);
    sprintf(text, "%02d", curr_time.tm_sec);
    OLED_ShowString(98, 28, (const uint8_t*)text, 16, 1);
    // display week day
    OLED_ShowHzStringRow(72, 48, (const char*)"星期", 1);
    OLED_ShowHzStringRow(104, 48, (const char*)hz_week_char[curr_time.tm_wday], 1);
    if (flag >= DISP_MAIN_CUT_TIME)
    {
        flag = 0U;
    }
    if (flag >= (uint8_t)(DISP_MAIN_CUT_TIME>>1U))
    {
        memset (text, 0 , sizeof(text));
        sprintf(text, "%04d", curr_time.tm_year+1900);
        OLED_ShowString(8, 48, (const uint8_t*)text, 16, 1);
        OLED_ShowHzStringRow(40, 48, (const char*)"年", 1);
    }
    else
    {
        memset (text, 0 , sizeof(text));
        sprintf(text, "%02d  %02d", curr_time.tm_mon+1, curr_time.tm_mday);
        OLED_ShowString(0, 48, (const uint8_t*)text, 16, 1);
        OLED_ShowHzStringRow(16, 48, (const char*)"月", 1);
        OLED_ShowHzStringRow(48, 48, (const char*)"日", 1);
    }
    
    // display humidity and temperature
	humi_temp = Hs300x_ReadData();
    if (flag >= (uint8_t)(DISP_MAIN_CUT_TIME>>1U))
    {
        memset (text, 0 , sizeof(text));
        sprintf(text, "%.2f%%", humi_temp.humi);
        x = 64 + (uint8_t)((64 - (uint8_t)(strlen(text) << 3)) / 2);
        OLED_ShowString(x, 0, (const uint8_t*)text, 16, 1);
    }
    else
    {
        memset (text, 0 , sizeof(text));
        sprintf(text, "%.1f", humi_temp.temp);
        x = 64 + (uint8_t)((64 - ((strlen(text) << 3) + 16)) / 2);
        OLED_ShowString(x, 0, (const uint8_t*)text, 16, 1);
        x = x + (uint8_t)(strlen(text) << 3);
        OLED_ShowHzStringRow(x, 0, (const char*)"℃", 1);
    }
	
	// display wifi logo
    if (WIFI_CONNECTED == Wifi_GetApConnStatus())
    {
        OLED_DrawBmpImg2(0, 0, wifi_logo_16bit, LOGO_SIZE(wifi_logo_16bit), 16, 1);
    }
    else
    {
        if (1U == conn_flag)
        {
            OLED_DrawBmpImg2(0, 0, wifi_logo_16bit, LOGO_SIZE(wifi_logo_16bit), 16, 1);
        }
        else
        {
            // Do nothing
        }
    }

    // display IOT connect log
    if (WIFI_ONENET_CONNECTED == Wifi_GetIotConnStatus())
    {
        OLED_ShowString(32, 0, (const uint8_t*)"IoT", 16, 1);
    }
    else
    {
        if (1U == conn_flag)
        {
            OLED_ShowString(32, 0, (const uint8_t*)"IoT", 16, 1);
        }
        else
        {
            // Do nothing
        }
    }

    // display buletooth logo
    if (BT_CONNECTED == Bt_GetConnectStatus())
    {
        OLED_DrawBmpImg2(16, 0, bt_logo_16bit, LOGO_SIZE(bt_logo_16bit), 16, 1);
    }
    else
    {
        if (1U == conn_flag)
        {
            OLED_DrawBmpImg2(16, 0, bt_logo_16bit, LOGO_SIZE(bt_logo_16bit), 16, 1);
        }
        else
        {
            // Do nothing
        }
    }

    // refresh OLED
    OLED_Refresh_Gram();

    flag ++;
    conn_flag ^= 1;
}

// Display sensor information: humidity/temperature/light strength
static void Disp_SensorMonitor(void)
{
    char text[16];
    s_Hs300xDataType humi_temp;
	uint32_t lux;
    uint32_t gas_ppm;

    humi_temp = Hs300x_ReadData();
#ifdef DISP_DEBUG
	LOG("humidity: %.2f%%, temperature: %.2fC\n", humi_temp.humi, humi_temp.temp);
#endif
		
	lux = Isl29035_ReadData();
#ifdef DISP_DEBUG
	LOG("Lux: %u\n", lux);
#endif

    gas_ppm = Mq5_GetGasPpmValue();

    // Humidity
    memset (text, 0 , sizeof(text));
    sprintf(text, "Humi:%.2f%% ", humi_temp.humi);
    OLED_ShowString(0, 0, (const uint8_t*)text, 16, 1);
    // Temperature
    memset (text, 0 , sizeof(text));
    sprintf(text, "Temp:%.2f ", humi_temp.temp);
    OLED_ShowString(0, 16, (const uint8_t*)text, 16, 1);
    OLED_ShowHzStringRow((uint8_t)(strlen(text)<<3U), 16, (const char*)"℃", 1);
    // Ambient light sensing
    memset (text, 0 , sizeof(text));
    sprintf(text, "ALS:%uLux ", lux);
    OLED_ShowString(0, 32, (const uint8_t*)text, 16, 1);
    // Combustible gas concentration
    memset (text, 0 , sizeof(text));
    sprintf(text, "CGC:%uppm ", gas_ppm);
    OLED_ShowString(0, 48, (const uint8_t*)text, 16, 1);  

    OLED_Refresh_Gram();
}

// Display the Lamp control
static void Disp_LampCtrl(void)
{

}

// Display main interface for task
void Disp_RunningEntry(void)
{
    OLED_Clear();
    disp_list[disp_variant].disp_func();

    DELAY_MS(disp_list[last_disp_variant].delay_time);

    last_disp_variant = disp_variant;
}

void Disp_Change(void)
{
    switch (disp_variant)
    {
        case DISP_MAIN_MENU:
        {
            disp_variant = DISP_ENVIR;
            break;
        }
        case DISP_ENVIR:
        {
            disp_variant = DISP_MAIN_MENU;
            break;
        }
        default: break;
    }
}


